 /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package MVC;

import common.Bye;
import common.TransfertFileRequest;
import common.Hello;
import common.Message;
import common.Fichier;
import common.Text;
import common.TransfertFileAccept;
import ChatNI.*;
import MVC.*;
import InterfaceUser.*;
import java.io.File;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * ChatController
 * The controller in the MVC pattern
 * @author Duy Duc, Metangmo
 */
public class ChatController {
     
     //Message factory
     private Usine factory;
     //Nickname of the LocalUser
     private String username;
     
     //MVC
     private ModelUser modele ;
     private ModelMessIn modeleMessIn;
     private ModelMessOut modeleMessOut;
     private UDPcom udp;   
     private TCPcom tcp;
     private ChatGUI gui;
     
     //Attributes concern a file transfer
     private File fileToSend;
     private File directoryToStore;

     /**
      * Constructor
      */
     public ChatController() {
          // Establishment of the factory to produce the messages
          this.factory = new Usine();
      
     }
     
     /**
      * performConnect:
      * function sends the Hello-True message to all the exist connected user on the network when the LocalUser logs in
      * and updates the ModelMessOut who is the model of the MVC pattern
      * This function is called by the threads of button Connect
      * @param user
      *        The nickname that the LocalUser uses to log in to the ChatSystem
      * @throws UnknownHostException
      * @throws SocketException 
      */
     
     public void performConnect(String user) throws UnknownHostException, SocketException{
         
         
         // Nickname of the LocalUser is updated
         this.username = user;
         
         // Hello-True message is sent in broadcast
          Message message = factory.formerMessage(FabriqueMessage.TypeMessage.HELLO, InetAddress.getLocalHost(), username,Boolean.TRUE,null);
         
          //The message is enregisted in the ModelMessOut for sending to UDPcom
          modeleMessOut.addNouveauMessOut(message, InetAddress.getByName("255.255.255.255"));
          modeleMessOut.addNouveauMessOut(message, InetAddress.getByName("255.255.255.255"));
     }
      
    /**
     * performSendMessage:
     * function sends the different types of message to a user/a group of users on the network
     * and updates the ModelMessOut who is the model of the MVC pattern 
     * @param type
     *        Type of the sent message ( HELLO, BYE, TEXT )
     * @param addr
     *        IP Address of the recipient
     * @param username
     *        Nickname of the LocalUser
     * @param boo
     *        True/False signifies a demand of connection/a demand of addition in a list of user for the HELLO message
     * @param texte
     *        The content of the TEXT message
     * @throws UnknownHostException 
     */ 
     
    public void performSendMessage(FabriqueMessage.TypeMessage type, InetAddress addr, String username, Boolean boo, String texte) throws UnknownHostException
    {
         //Creation of the message
         Message message2 = factory.formerMessage(type,InetAddress.getLocalHost() ,username, boo, texte);

         //The message is enregisted in the ModelMessOut for sending to UDPcom
         // addr represents the recipient's IP Address
         modeleMessOut.addNouveauMessOut(message2, addr);
         modeleMessOut.addNouveauMessOut(message2, addr);
         
    }
     
    /**
     * performSendFile:
     * function sends the different messages corresponds with a file transfer
     * and updates the ModelMessOut who is the model of the MVC pattern 
     * @param type
     *        Type of the sent message ( TRANSFERTFILEACCEPT, TRANSFERTFILEREQUEST, FICHIER )
     * @param addr
     *        IP Address of the recipient
     * @param tailleFic
     *        Size of the file
     * @param fic
     *        Pointer to the file
     * @param acc
     *        True/False signifies the accept/the deny of the TRANSFERTFILEACCEPT message
     * @param nomFic
     *        Name of the file
     * @throws UnknownHostException 
     */ 
    public void performSendFile(FabriqueFile.TypeMessage type, InetAddress addr,int tailleFic, File fic, Boolean acc,String nomFic) throws UnknownHostException
    {
         //Creation of the message 
         Message message2 = factory.formerFile(type,InetAddress.getLocalHost() ,tailleFic, fic, acc,nomFic);
         
         //The message is enregisted in the ModelMessOut for sending to UDPcom
         // addr represents the recipient's IP Address
         modeleMessOut.addNouveauMessOut(message2, addr);
         modeleMessOut.addNouveauMessOut(message2, addr);

         
         if ( type == (FabriqueFile.TypeMessage.TRANSFERTFILEACCEPT) && (acc == true) ) {
             
             System.out.println ("I responded 'Yes' for the demand of file transfer! ");
         }
    }
     
    /**
     * performReceiveMessage:
     * function receives the messages from the users on the network, treats them depending on their type
     * and updates the ModelMessIn who is the model of the MVC pattern
     * @param mess
     *        Received message
     * @throws UnknownHostException 
     */
    public void performReceiveMessage(Message mess ) throws UnknownHostException
    {
         //Hello message
         if (mess instanceof Hello){
             Hello mess2 = (Hello) mess;
             System.out.println("Adresse :" + mess2.getAddr());
             System.out.println("Nom :"+ mess2.getUsername());
             System.out.println("Valeur_booléen :"+ mess2.getReply());
             
             //Reception a Hello-True message
             if ( mess2.getReply() == true ) {
                 
                 //Hello-False is sent to the Hello-True sender
                 Message message2 = factory.formerMessage(FabriqueMessage.TypeMessage.HELLO,InetAddress.getLocalHost(), username,Boolean.FALSE,null);
                 
                 udp.sendMess(message2,mess2.getAddr());
                 
                 System.out.println("Reception of Hello-True => Send Hello-False");
             }
 
                 //the nickname and the IP address of the sender is added in the information table in the ModelUser
                 modele.addToList(mess2.getAddr(),mess2.getUsername());

         } 
         //Bye message
         else if(mess instanceof Bye) {
                Bye mess2 = (Bye) mess;
                System.out.println("Goodbye!");

                //Remove the sender from the information table in the ModelUser
                modele.removeFromList(mess2.getAddr());
                
         }
         //TransfertFileRequest message
         else if(mess instanceof TransfertFileRequest) {
                TransfertFileRequest mess2 = (TransfertFileRequest) mess;
                
                //Show the LocalUser the demand of file transfer
                System.out.println("RequestFileTransfer received! ");
                gui.fileReceiveDemand(modele.userList.get(mess2.getAddr()));
                
         }
         //TransfertFileAccept message
         else if(mess instanceof TransfertFileAccept) {
                TransfertFileAccept mess2 = (TransfertFileAccept) mess;
                System.out.println(" RequestFileAccept");
                System.out.println(" Reponse is :"+mess2.getAccept());
                System.out.println(" Reponse from :"+mess2.getAddr());
                
                //Demand is accepted
                if ( mess2.getAccept() == true ){
                    
                    //The file is made
                    Message message2 = factory.formerFile (FabriqueFile.TypeMessage.FICHIER,InetAddress.getLocalHost() ,0, fileToSend, null,null);
                    
                    //The message is enregisted in the ModelMessOut for sending to UDPcom
                    modeleMessOut.addNouveauMessOut(message2, mess2.getAddr());
                    modeleMessOut.addNouveauMessOut(message2, mess2.getAddr());
                    
                    // Ecriture dans l'aire de réception de l'utlisateur du message fichier transmis:
                    //Writes in the reception area of the onscreen user a message annoncing that the file is transmitted
                    Message message3 = factory.formerMessage(FabriqueMessage.TypeMessage.TEXT,mess2.getAddr(), null,Boolean.FALSE, " File is sent! ");
                    
                    //The message is enregisted in the ModelMessIn for sending to ChatGUI
                    modeleMessIn.addNouveauMessIn((Text) message3);
                    
                }
                
         }
         //Text message
         else if(mess instanceof Text) {
                Text mess2 = (Text) mess;
                System.out.println("Received text : " + mess2.getContent());
                
                //The message is enregisted in the ModelMessIn for sending to ChatGUI
                modeleMessIn.addNouveauMessIn(mess2);
                
         }
         //File message
         else if(mess instanceof Fichier) {
                Fichier mess2 = (Fichier) mess;
                
                // TODO : Save the file in the computer
         }
         //Problem!!!
         else {
               System.out.println("No type is detected!!!");
         }
        
    }
    
    /**
     * performReceiveNotification:
     * function updates the ModelMessIn who is the model of the MVC pattern 
     * when there is a notification on the file transfer
     * The notifications are displayed in the tab About
     * @param notification
     *        Content of the notification
     */
    public void  performReceiveNotification(String notification){
        
        modeleMessIn.addNotification(notification);
    }

    /**
     * setFichierToSend:
     * function defines the file for sending
     * @param fileToSend
     *        File to sendMess
     */ 
    public void setFileToSend(File fileToSend) {
        this.fileToSend = fileToSend;
    }

    
    /**
     * setDirectoryToStore
     * function defines the position to store the received file 
     * @param directoryToStore
     *        Directory to store the file
     */
    public void setDirectoryToStore(File directoryToStore) {
        this.directoryToStore = directoryToStore;
    }
    
    /**
     * getDirectoryToStore:
     * function returns the position to store the received file
     * @return
     *        The path to the position of the received file
     */
    public File getDirectoryToStore() {
        return directoryToStore;
    }
    
    
    /**
     * stop:
     * function stops the threads of the UDP/TCP connection
     */
    
    public void stop() {
        
        udp.stop();
        System.out.println("closed controller");
    }
    
    
    
    /**************** MODEL VIEW CONTROL ************/
    //Model addition
    public void addModel(ModelUser modele){
        this.modele=modele;   
    }
    
    public void addModelMessIn(ModelMessIn modeleMessIn){
        this.modeleMessIn=modeleMessIn;   
    }

    public void addModelMessOut(ModelMessOut modeleMessOut) {
        this.modeleMessOut = modeleMessOut;
    }

    
    //View addition
    public void addView(ChatGUI gui){
        this.gui=gui;
    }
    
    public void setUdp(UDPcom udp) {
        this.udp = udp;
    }

    public TCPcom getTcp() {
        return tcp;
    }
     
     public void setTcp(TCPcom tcp) {
        this.tcp = tcp;
    }
    
    //Get the models
    public ModelUser getModele() {
        return modele;
    }
    
    public ModelMessIn getModeleMessIn() {
        return modeleMessIn;
    }

    public ModelMessOut getModeleMessOut() {
        return modeleMessOut;
    }
    
    
   
}